123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- // SPDX-FileCopyrightText: Adam Evyčędo
- //
- // SPDX-License-Identifier: AGPL-3.0-or-later
- package server
- import (
- "fmt"
- "apiote.xyz/p/szczanieckiej/config"
- "apiote.xyz/p/szczanieckiej/traffic"
- "net/http"
- "net/url"
- "strings"
- "git.sr.ht/~sircmpwn/go-bare"
- "golang.org/x/text/language"
- )
- type AbstractHandlerVars interface {
- getWriter() http.ResponseWriter
- getRequest() *http.Request
- getTraffic() *traffic.Traffic
- getConfig() config.Config
- getAccept() map[uint]struct{}
- getFeedName() string
- getPath() []string
- setPath([]string)
- getVersionCode() traffic.Validity
- setVersionCode(traffic.Validity)
- getContext() traffic.Context
- setContext(traffic.Context)
- getAcceptLanguage() string
- setAcceptLanguage(string)
- getPreferredLanguages() []language.Tag
- setPreferredLanguages([]language.Tag)
- getResponse() any
- setResponse(any)
- getResponseBytes() []byte
- setResponseBytes([]byte)
- }
- type HandlerVars struct {
- w http.ResponseWriter
- r *http.Request
- t *traffic.Traffic
- c config.Config
- a map[uint]struct{}
- f string
- path []string
- versionCode traffic.Validity
- context traffic.Context
- acceptLanguage string
- preferredLanguages []language.Tag
- response any
- responseBytes []byte
- }
- func (v HandlerVars) getWriter() http.ResponseWriter {
- return v.w
- }
- func (v HandlerVars) getRequest() *http.Request {
- return v.r
- }
- func (v HandlerVars) getTraffic() *traffic.Traffic {
- return v.t
- }
- func (v HandlerVars) getConfig() config.Config {
- return v.c
- }
- func (v HandlerVars) getAccept() map[uint]struct{} {
- return v.a
- }
- func (v HandlerVars) getFeedName() string {
- return v.f
- }
- func (v HandlerVars) getPath() []string {
- return v.path
- }
- func (v *HandlerVars) setPath(p []string) {
- v.path = p
- }
- func (v HandlerVars) getVersionCode() traffic.Validity {
- return v.versionCode
- }
- func (v *HandlerVars) setVersionCode(c traffic.Validity) {
- v.versionCode = c
- }
- func (v HandlerVars) getContext() traffic.Context {
- return v.context
- }
- func (v *HandlerVars) setContext(c traffic.Context) {
- v.context = c
- }
- func (v HandlerVars) getAcceptLanguage() string {
- return v.acceptLanguage
- }
- func (v *HandlerVars) setAcceptLanguage(l string) {
- v.acceptLanguage = l
- }
- func (v HandlerVars) getPreferredLanguages() []language.Tag {
- return v.preferredLanguages
- }
- func (v *HandlerVars) setPreferredLanguages(t []language.Tag) {
- v.preferredLanguages = t
- }
- func (v HandlerVars) getResponse() any {
- return v.response
- }
- func (v *HandlerVars) setResponse(r any) {
- v.response = r
- }
- func (v HandlerVars) getResponseBytes() []byte {
- return v.responseBytes
- }
- func (v *HandlerVars) setResponseBytes(b []byte) {
- v.responseBytes = b
- }
- func splitPath(v AbstractHandlerVars) (AbstractHandlerVars, error) {
- escapedPath := strings.Split(v.getRequest().URL.EscapedPath()[1:], "/")
- path := make([]string, len(escapedPath))
- var err error
- for i, segment := range escapedPath {
- path[i], err = url.PathUnescape(segment)
- if err != nil {
- return v, fmt.Errorf("while unescaping path segment ‘%s’: %w", segment, err)
- }
- }
- v.setPath(path)
- return v, nil
- }
- func prepareForm(v AbstractHandlerVars) {
- v.getRequest().ParseForm()
- }
- func getVersionCode(v AbstractHandlerVars) (AbstractHandlerVars, error) {
- dateString := v.getRequest().Form.Get("date")
- versionCode, _, err := parseDate(dateString, v.getFeedName(), v.getTraffic())
- v.setVersionCode(versionCode)
- return v, err
- }
- func createContext(v AbstractHandlerVars) AbstractHandlerVars {
- v.setContext(
- traffic.Context{
- DataHome: v.getConfig().FeedsPath,
- FeedID: v.getFeedName(),
- Version: v.getVersionCode(),
- },
- )
- return v
- }
- func getAcceptLanguage(v AbstractHandlerVars) AbstractHandlerVars {
- v.setAcceptLanguage(v.getRequest().Header.Get("Accept-Language"))
- if v.getAcceptLanguage() == "" {
- v.setAcceptLanguage("und")
- }
- return v
- }
- func parseAcceptLanguage(v AbstractHandlerVars) (AbstractHandlerVars, error) {
- preferredLanguages, _, err := language.ParseAcceptLanguage(v.getAcceptLanguage())
- if err != nil {
- return v, ServerError{
- code: http.StatusBadRequest,
- field: "Accept-Language",
- value: v.getAcceptLanguage(),
- err: err,
- }
- }
- v.setPreferredLanguages(preferredLanguages)
- return v, nil
- }
- func marshalResponse(v AbstractHandlerVars) (AbstractHandlerVars, error) {
- r := v.getResponse()
- bytes, err := bare.Marshal(&r)
- v.setResponseBytes(bytes)
- return v, err
- }
- func writeResponse(v AbstractHandlerVars) error {
- _, err := v.getWriter().Write(v.getResponseBytes())
- return err
- }
|