roobre/ffxivapi

View on GitHub
http/http.go

Summary

Maintainability
A
0 mins
Test Coverage
package http

import (
    "encoding/json"
    "errors"
    "github.com/gorilla/mux"
    log "github.com/sirupsen/logrus"
    "github.com/swaggo/http-swagger"
    "net/http"
    "roob.re/ffxivapi"
    "roob.re/ffxivapi/lodestone"
    "strconv"
)

type Api struct {
    *mux.Router
    xivapi *ffxivapi.FFXIVAPI
}

func New() *Api {
    return NewWithApi(ffxivapi.New())
}

func NewWithApi(api *ffxivapi.FFXIVAPI) *Api {
    h := &Api{
        Router: mux.NewRouter(),
        xivapi: api,
    }

    h.Use(logRequest)
    h.Handle("/", http.RedirectHandler("/doc/", http.StatusMovedPermanently))
    h.HandleFunc("/character/search", h.search)
    h.HandleFunc("/character/{id}", h.character)
    h.HandleFunc("/character/{id}/avatar", h.characterAvatar)

    h.Handle("/swagger.yaml", http.FileServer(http.Dir("http")))
    h.PathPrefix("/doc").Handler(httpSwagger.Handler(httpSwagger.URL("/swagger.yaml")))

    return h
}

func (h *Api) search(rw http.ResponseWriter, r *http.Request) {
    name := r.FormValue("name")
    world := r.FormValue("world")
    if name == "" || world == "" {
        rw.WriteHeader(http.StatusBadRequest)
        return
    }

    results, err := h.xivapi.Search(name, world)
    if err != nil {
        rw.WriteHeader(http.StatusBadGateway)
        rw.Write([]byte(err.Error()))
        return
    }

    if len(results) == 0 {
        rw.WriteHeader(http.StatusNotFound)
    }

    rw.Header().Add("content-type", "application/json")

    je := json.NewEncoder(rw)
    je.Encode(results)
}

func (h *Api) character(rw http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id, err := strconv.Atoi(vars["id"])
    if err != nil {
        rw.WriteHeader(http.StatusBadRequest)
        return
    }

    features := uint(0)
    if r.FormValue("achievements") != "" {
        features |= ffxivapi.FeatureAchievements
    }
    if r.FormValue("classjob") != "" {
        features |= ffxivapi.FeatureClassJob
    }

    character, err := h.xivapi.Character(id, features)
    var herr lodestone.HTTPError
    if errors.As(err, &herr) && herr == http.StatusNotFound {
        rw.WriteHeader(http.StatusNotFound)
        return
    } else if err != nil {
        rw.WriteHeader(http.StatusBadGateway)
        rw.Write([]byte(err.Error()))
        return
    }

    rw.Header().Add("content-type", "application/json")

    je := json.NewEncoder(rw)
    je.Encode(character)
}

func (h *Api) characterAvatar(rw http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id, err := strconv.Atoi(vars["id"])
    if err != nil {
        rw.WriteHeader(http.StatusBadRequest)
        return
    }

    character, err := h.xivapi.Character(id, 0)
    var herr lodestone.HTTPError
    if errors.As(err, &herr) && herr == http.StatusNotFound {
        rw.WriteHeader(http.StatusNotFound)
        return
    } else if err != nil {
        rw.WriteHeader(http.StatusBadGateway)
        rw.Write([]byte(err.Error()))
        return
    }

    http.Redirect(rw, r, character.Avatar, http.StatusFound)
}

func logRequest(handler http.Handler) http.Handler {
    return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
        log.Info(request.RequestURI)
        handler.ServeHTTP(writer, request)
    })
}