#1: Integrate queue to the application

This commit is contained in:
ErickSkrauch
2019-04-27 01:46:15 +03:00
parent f3690686ec
commit f7cdab243f
12 changed files with 298 additions and 117 deletions

View File

@@ -14,13 +14,26 @@ func (cfg *Config) Cape(response http.ResponseWriter, request *http.Request) {
username := parseUsername(mux.Vars(request)["username"])
rec, err := cfg.CapesRepo.FindByUsername(username)
if err != nil {
http.Redirect(response, request, "http://skins.minecraft.net/MinecraftCloaks/" + username + ".png", 301)
if err == nil {
request.Header.Set("Content-Type", "image/png")
io.Copy(response, rec.File)
return
}
request.Header.Set("Content-Type", "image/png")
io.Copy(response, rec.File)
mojangTextures := <-cfg.MojangTexturesQueue.GetTexturesForUsername(username)
if mojangTextures == nil {
response.WriteHeader(http.StatusNotFound)
return
}
texturesProp := mojangTextures.DecodeTextures()
cape := texturesProp.Textures.Cape
if cape == nil {
response.WriteHeader(http.StatusNotFound)
return
}
http.Redirect(response, request, cape.Url, 301)
}
func (cfg *Config) CapeGET(response http.ResponseWriter, request *http.Request) {

View File

@@ -19,10 +19,11 @@ import (
type Config struct {
ListenSpec string
SkinsRepo interfaces.SkinsRepository
CapesRepo interfaces.CapesRepository
Logger wd.Watchdog
Auth interfaces.AuthChecker
SkinsRepo interfaces.SkinsRepository
CapesRepo interfaces.CapesRepository
MojangTexturesQueue interfaces.MojangTexturesQueue
Logger wd.Watchdog
Auth interfaces.AuthChecker
}
func (cfg *Config) Run() error {

View File

@@ -5,34 +5,41 @@ import (
"net/http"
"strings"
"github.com/elyby/chrly/api/mojang"
"github.com/gorilla/mux"
"github.com/elyby/chrly/api/mojang"
)
func (cfg *Config) SignedTextures(response http.ResponseWriter, request *http.Request) {
cfg.Logger.IncCounter("signed_textures.request", 1)
username := parseUsername(mux.Vars(request)["username"])
var responseData *mojang.SignedTexturesResponse
rec, err := cfg.SkinsRepo.FindByUsername(username)
if err != nil || rec.SkinId == 0 || rec.MojangTextures == "" {
response.WriteHeader(http.StatusNoContent)
return
if err == nil && rec.SkinId != 0 && rec.MojangTextures != "" {
responseData = &mojang.SignedTexturesResponse{
Id: strings.Replace(rec.Uuid, "-", "", -1),
Name: rec.Username,
Props: []*mojang.Property{
{
Name: "textures",
Signature: rec.MojangSignature,
Value: rec.MojangTextures,
},
{
Name: "chrly",
Value: "how do you tame a horse in Minecraft?",
},
},
}
} else if request.URL.Query().Get("proxy") != "" {
responseData = <-cfg.MojangTexturesQueue.GetTexturesForUsername(username)
}
responseData := mojang.SignedTexturesResponse{
Id: strings.Replace(rec.Uuid, "-", "", -1),
Name: rec.Username,
Props: []*mojang.Property{
{
Name: "textures",
Signature: rec.MojangSignature,
Value: rec.MojangTextures,
},
{
Name: "chrly",
Value: "how do you tame a horse in Minecraft?",
},
},
if responseData == nil {
response.WriteHeader(http.StatusNoContent)
return
}
responseJson, _ := json.Marshal(responseData)

View File

@@ -13,12 +13,25 @@ func (cfg *Config) Skin(response http.ResponseWriter, request *http.Request) {
username := parseUsername(mux.Vars(request)["username"])
rec, err := cfg.SkinsRepo.FindByUsername(username)
if err != nil || rec.SkinId == 0 {
http.Redirect(response, request, "http://skins.minecraft.net/MinecraftSkins/" + username + ".png", 301)
if err == nil && rec.SkinId != 0 {
http.Redirect(response, request, rec.Url, 301)
return
}
http.Redirect(response, request, rec.Url, 301)
mojangTextures := <-cfg.MojangTexturesQueue.GetTexturesForUsername(username)
if mojangTextures == nil {
response.WriteHeader(http.StatusNotFound)
return
}
texturesProp := mojangTextures.DecodeTextures()
skin := texturesProp.Textures.Skin
if skin == nil {
response.WriteHeader(http.StatusNotFound)
return
}
http.Redirect(response, request, skin.Url, 301)
}
func (cfg *Config) SkinGET(response http.ResponseWriter, request *http.Request) {

View File

@@ -1,102 +1,64 @@
package http
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"io"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
"github.com/elyby/chrly/model"
"github.com/elyby/chrly/api/mojang"
)
type texturesResponse struct {
Skin *Skin `json:"SKIN"`
Cape *Cape `json:"CAPE,omitempty"`
}
type Skin struct {
Url string `json:"url"`
Hash string `json:"hash"`
Metadata *skinMetadata `json:"metadata,omitempty"`
}
type skinMetadata struct {
Model string `json:"model"`
}
type Cape struct {
Url string `json:"url"`
Hash string `json:"hash"`
}
func (cfg *Config) Textures(response http.ResponseWriter, request *http.Request) {
cfg.Logger.IncCounter("textures.request", 1)
username := parseUsername(mux.Vars(request)["username"])
var textures *mojang.TexturesResponse
skin, err := cfg.SkinsRepo.FindByUsername(username)
if err != nil || skin.SkinId == 0 {
if skin == nil {
skin = &model.Skin{}
if err == nil && skin.SkinId != 0 {
textures = &mojang.TexturesResponse{
Skin: &mojang.SkinTexturesResponse{
Url: skin.Url,
},
}
skin.Url = "http://skins.minecraft.net/MinecraftSkins/" + username + ".png"
skin.Hash = string(buildNonElyTexturesHash(username))
}
textures := texturesResponse{
Skin: &Skin{
Url: skin.Url,
Hash: skin.Hash,
},
}
if skin.IsSlim {
textures.Skin.Metadata = &skinMetadata{
Model: "slim",
}
}
cape, err := cfg.CapesRepo.FindByUsername(username)
if err == nil {
var scheme string = "http://"
if request.TLS != nil {
scheme = "https://"
if skin.IsSlim {
textures.Skin.Metadata = &mojang.SkinTexturesMetadata{
Model: "slim",
}
}
textures.Cape = &Cape{
Url: scheme + request.Host + "/cloaks/" + username,
Hash: calculateCapeHash(cape),
_, err = cfg.CapesRepo.FindByUsername(username)
if err == nil {
var scheme = "http://"
if request.TLS != nil {
scheme = "https://"
}
textures.Cape = &mojang.CapeTexturesResponse{
Url: scheme + request.Host + "/cloaks/" + username,
}
}
} else {
mojangTextures := <-cfg.MojangTexturesQueue.GetTexturesForUsername(username)
if mojangTextures == nil {
// TODO: test compatibility with exists authlibs
response.WriteHeader(http.StatusNoContent)
return
}
texturesProp := mojangTextures.DecodeTextures()
if texturesProp == nil {
// TODO: test compatibility with exists authlibs
response.WriteHeader(http.StatusInternalServerError)
cfg.Logger.Error("Unable to find textures property")
return
}
textures = texturesProp.Textures
}
responseData, _ := json.Marshal(textures)
response.Header().Set("Content-Type", "application/json")
response.Write(responseData)
}
func calculateCapeHash(cape *model.Cape) string {
hasher := md5.New()
io.Copy(hasher, cape.File)
return hex.EncodeToString(hasher.Sum(nil))
}
func buildNonElyTexturesHash(username string) string {
hour := getCurrentHour()
hasher := md5.New()
hasher.Write([]byte("non-ely-" + strconv.FormatInt(hour, 10) + "-" + username))
return hex.EncodeToString(hasher.Sum(nil))
}
var timeNow = time.Now
func getCurrentHour() int64 {
n := timeNow()
return time.Date(n.Year(), n.Month(), n.Day(), n.Hour(), 0, 0, 0, time.UTC).Unix()
}