...
 
Commits (2)
......@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
"errors"
"git.kuschku.de/justjanne/bahn-api"
"github.com/go-redis/cache"
"github.com/go-redis/redis"
......@@ -15,24 +16,32 @@ type RedisCache struct {
func (m RedisCache) Set(key string, value interface{}) error {
return m.backend.Set(&cache.Item{
Key: key,
Object: value,
Key: key,
Object: value,
Expiration: m.expirationTime,
})
}
func (m RedisCache) Get(key string, value interface{}) error {
return m.backend.Get(key, &value)
err := m.backend.Get(key, &value)
if err != nil {
return err
} else if value == nil {
return errors.New("redis returned empty result")
}
return nil
}
func NewRedisCache(expirationTime time.Duration) bahn.CacheBackend {
func NewRedisCache(address string, password string, expirationTime time.Duration) bahn.CacheBackend {
return RedisCache{
backend: &cache.Codec{
Redis: redis.NewClient(&redis.Options{
Addr: address,
Password: password,
}),
Marshal: json.Marshal,
Unmarshal: json.Unmarshal,
},
expirationTime: expirationTime,
}
}
package main
import "time"
type Config struct {
Endpoints EndpointConfig `yaml:"endpoints"`
Caches CacheConfig `yaml:"caches"`
RequestTimeout time.Duration `yaml:"request_timeout"`
MaxResults int `yaml:"max_results"`
}
type EndpointConfig struct {
Iris string `yaml:"iris"`
CoachSequence string `yaml:"coach_sequence"`
Hafas string `yaml:"hafas"`
}
type CacheConfig struct {
Redis RedisCacheConfig `yaml:"redis"`
Memory MemoryCacheConfig `yaml:"memory"`
}
type RedisCacheConfig struct {
Address string `yaml:"address"`
Password string `yaml:"password"`
Timeout time.Duration `yaml:"timeout"`
}
type MemoryCacheConfig struct {
Timeout time.Duration `yaml:"timeout"`
}
......@@ -3,8 +3,10 @@ module git.kuschku.de/justjanne/bahn-proxy
go 1.12
require (
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504160313-5e30ecd44bd3
github.com/go-redis/cache v6.3.5+incompatible
github.com/go-redis/redis v6.15.2+incompatible
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/patrickmn/go-cache v2.1.0+incompatible
gopkg.in/yaml.v2 v2.2.2
)
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812 h1:dhL0LHGoud1so9Be3namg7g+/PtGVGhldtw+agNActg=
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504114009-71c830fe0812/go.mod h1:WQsAQzBR+0dlaVVuwwkx8j5uMoWDIdc8xtX4vlRrp5E=
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504155414-dc55c2c13a0e/go.mod h1:EHmQs/TNmFmd0+CqjhE28kCKTnWoEOaP3N3tS2vilPo=
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504160313-5e30ecd44bd3 h1:EJhvTmuP84iEgWirYHaIWObBoNcKuaaJPuNU0FrIg6k=
git.kuschku.de/justjanne/bahn-api v0.0.0-20190504160313-5e30ecd44bd3/go.mod h1:rzJ5eu/KKeWxt1lUkVioHhhuvPYNCOKU/VzTWPW3S38=
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/go-redis/cache v6.3.5+incompatible h1:4OUyoXXYRRQ6tKA4ue3TlPUkBzk3occzjtXBZBxCzgs=
github.com/go-redis/cache v6.3.5+incompatible/go.mod h1:XNnMdvlNjcZvHjsscEozHAeOeSE5riG9Fj54meG4WT4=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/google/logger v1.0.1/go.mod h1:w7O8nrRr0xufejBlQMI83MXqRusvREoJdaAxV+CoAB4=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01 h1:po1f06KS05FvIQQA2pMuOWZAUXiy1KYdIf0ElUU2Hhc=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
......@@ -2,10 +2,13 @@ package main
import (
"encoding/json"
"flag"
"fmt"
"git.kuschku.de/justjanne/bahn-api"
"gopkg.in/yaml.v2"
"log"
"net/http"
"os"
"path"
"sort"
"strconv"
......@@ -19,7 +22,7 @@ func returnJson(w http.ResponseWriter, data interface{}) error {
return err
}
w.Header().Add("Content-Type", "application/json")
w.Header().Add("Content-Type", "application/json; charset=utf-8")
if _, err := w.Write(marshalled); err != nil {
return err
}
......@@ -28,22 +31,41 @@ func returnJson(w http.ResponseWriter, data interface{}) error {
}
func main() {
var err error
configPath := flag.String("config", "config.yaml", "Path to config file")
listen := flag.String("listen", ":8080", "Listen address")
flag.Parse()
var configFile *os.File
if configFile, err = os.Open(*configPath); err != nil {
panic(err)
}
var config Config
if err = yaml.NewDecoder(configFile).Decode(&config); err != nil {
panic(err)
}
autocompleteStations := loadAutocompleteStations()
apiClient := bahn.ApiClient{
IrisBaseUrl: "http://iris.noncd.db.de/iris-tts",
CoachSequenceBaseUrl: "https://www.apps-bahn.de/wr/wagenreihung/1.0",
HafasBaseUrl: "https://reiseauskunft.bahn.de/bin",
IrisBaseUrl: config.Endpoints.Iris,
CoachSequenceBaseUrl: config.Endpoints.CoachSequence,
HafasBaseUrl: config.Endpoints.Hafas,
HttpClient: &http.Client{
Timeout: time.Second * 10,
Timeout: config.RequestTimeout,
},
Caches: []bahn.CacheBackend{
NewMemoryCache(5 * time.Minute),
NewMemoryCache(config.Caches.Memory.Timeout),
NewRedisCache(
config.Caches.Redis.Address,
config.Caches.Redis.Password,
config.Caches.Redis.Timeout,
),
},
}
MaxResults := 20
http.HandleFunc("/autocomplete/", func(w http.ResponseWriter, r *http.Request) {
if stationName := strings.TrimSpace(r.FormValue("name")); stationName != "" {
var perfectMatch []AutocompleteStation
......@@ -62,14 +84,14 @@ func main() {
contains = append(contains, station)
}
if len(perfectMatch)+len(prefix)+len(contains) >= MaxResults {
if len(perfectMatch)+len(prefix)+len(contains) >= config.MaxResults {
break
}
}
result := append(append(perfectMatch, prefix...), contains...)
if err := returnJson(w, result); err != nil {
log.Fatal(err)
log.Println(err)
return
}
} else if position, err := PositionFromString(strings.TrimSpace(r.FormValue("position"))); err == nil {
......@@ -87,8 +109,8 @@ func main() {
return result[i].Distance < result[j].Distance
})
if err := returnJson(w, result[:MaxResults]); err != nil {
log.Fatal(err)
if err := returnJson(w, result[:config.MaxResults]); err != nil {
log.Println(err)
return
}
}
......@@ -101,18 +123,18 @@ func main() {
var evaId int64
if evaId, err = strconv.ParseInt(rawEvaId, 10, 64); err != nil {
log.Fatal(err)
log.Println(err)
return
}
var stations []bahn.Station
if stations, err = apiClient.Station(evaId); err != nil {
log.Fatal(err)
log.Println(err)
return
}
if err = returnJson(w, stations); err != nil {
log.Fatal(err)
log.Println(err)
return
}
})
......@@ -124,7 +146,7 @@ func main() {
var evaId int64
if evaId, err = strconv.ParseInt(rawEvaId, 10, 64); err != nil {
log.Fatal(err)
log.Println(err)
return
}
......@@ -137,7 +159,7 @@ func main() {
var timetable bahn.Timetable
if timetable, err = apiClient.Timetable(evaId, date); err != nil {
log.Fatal(err)
log.Println(err)
return
}
for _, stop := range timetable.Stops {
......@@ -148,7 +170,7 @@ func main() {
var realtime bahn.Timetable
if realtime, err = apiClient.RealtimeAll(evaId, date); err != nil {
log.Fatal(err)
log.Println(err)
return
}
for _, stop := range realtime.Stops {
......@@ -161,11 +183,13 @@ func main() {
for key, combined := range data {
if combined.Timetable.Arrival != nil && combined.Timetable.Arrival.Wings != "" {
if combined.WingDefinition, err = apiClient.WingDefinition(combined.Timetable.StopId, combined.Timetable.Arrival.Wings); err != nil {
log.Fatal(err)
log.Println(err)
return
}
} else if combined.Timetable.Departure != nil && combined.Timetable.Departure.Wings != "" {
if combined.WingDefinition, err = apiClient.WingDefinition(combined.Timetable.StopId, combined.Timetable.Departure.Wings); err != nil {
log.Fatal(err)
log.Println(err)
return
}
}
data[key] = combined
......@@ -183,7 +207,8 @@ func main() {
searchQuery := fmt.Sprintf("%s %s", combined.Timetable.TripLabel.TripCategory, combined.Timetable.TripLabel.TripNumber)
var suggestions []bahn.Suggestion
if suggestions, err = apiClient.Suggestions(searchQuery, moment); err != nil {
log.Fatal(err)
log.Println(err)
return
}
var targetStation = timetable.Station
if combined.Timetable.Departure != nil {
......@@ -213,7 +238,8 @@ func main() {
for key, combined := range data {
if combined.TrainLink != "" {
if combined.HafasMessages, err = apiClient.HafasMessages(combined.TrainLink); err != nil {
log.Fatal(err)
log.Println(err)
return
}
}
data[key] = combined
......@@ -225,11 +251,11 @@ func main() {
}
if err = returnJson(w, result); err != nil {
log.Fatal(err)
log.Println(err)
return
}
})
if err := http.ListenAndServe(":8080", nil); err != nil {
if err := http.ListenAndServe(*listen, nil); err != nil {
log.Fatal(err)
}
}