// Команда bj-lk — Личный кабинет клиента (modules/lk), отдельный модуль, обновляется независимо. // // Ставится на любой веб-сервер клиента. Сам к базам данных НЕ подключается — // работает только с bj-server по HTTP API с ключом доступа. Клиент входит по // логину/паролю, видит свои бумаги и подаёт заявку на перевод другому брокеру. // // Настройка — через переменные окружения (служба: /etc/bj/lk.env) или флаги: // // BJ_URL адрес bj-server (напр. https://bj.example.ru) // BJ_KEY ключ доступа модуля (выдаётся в админке bj-server) // BJ_MODE direct | agent (agent — ядро подключается к кабинету само) // BJ_RENDER local | core (core — страницы собирает ядро, здесь ретранслятор) // LISTEN адрес прослушивания (по умолчанию :8081) // LK_TITLE название кабинета в шапке (по умолчанию «Личный кабинет») // // Режим agent нужен, когда у ядра нет адреса, доступного из интернета: тогда адрес // ядра не задаётся, а кабинет ждёт, пока ядро подключится к нему само. package main import ( "flag" "fmt" "log" "net/http" "os" "strings" "time" "git.zetit.ru/zuevav/Bridge-and-Join-s/modules/lk" ) // version — версия модуля (go build -ldflags "-X main.version=…"). var version = "0.1.0" func main() { cfg := lk.Config{BJURL: os.Getenv("BJ_URL"), BJKey: os.Getenv("BJ_KEY"), Title: os.Getenv("LK_TITLE"), Agent: strings.EqualFold(strings.TrimSpace(os.Getenv("BJ_MODE")), "agent"), Relay: strings.EqualFold(strings.TrimSpace(os.Getenv("BJ_RENDER")), "core")} listen := os.Getenv("LISTEN") flag.BoolVar(&cfg.Agent, "agent", cfg.Agent, "режим ожидания: ядро подключается к кабинету само") flag.StringVar(&cfg.BJURL, "bj-url", cfg.BJURL, "адрес bj-server (https://...)") flag.StringVar(&cfg.BJKey, "bj-key", cfg.BJKey, "ключ доступа модуля") flag.StringVar(&listen, "listen", listen, "адрес прослушивания (:8081)") flag.StringVar(&cfg.Title, "title", cfg.Title, "заголовок кабинета") showVersion := flag.Bool("version", false, "показать версию") flag.Parse() if *showVersion { fmt.Println("bj-lk", version) return } if listen == "" { listen = ":8081" } // Настройки из файла веб-установщика (data/lk.json); окружение и флаги их перекрывают. dataDir := lk.DefaultDataDir() cfg, err := lk.LoadConfigFile(dataDir, cfg) if err != nil { log.Printf("bj-lk: %v", err) } srv, err := lk.New(cfg) if err != nil { log.Fatalf("bj-lk: %v", err) } srv.SetDataDir(dataDir) if !srv.Configured() { log.Printf("bj-lk: кабинет не настроен — откройте его адрес в браузере, запустится установщик (или задайте BJ_KEY и адрес ядра в окружении)") } if srv.InsecureCore() { // Не отказываем в запуске (бывают закрытые сети со своим шифрованием), // но это надо видеть в журнале: по такому каналу идут ключ и токены сессий. log.Printf("bj-lk: ВНИМАНИЕ — адрес ядра задан по открытому http (%s): ключ модуля и сессии клиентов пойдут по сети незашифрованными. Используйте https.", cfg.BJURL) } if cfg.Agent { log.Printf("bj-lk %s (Личный кабинет) слушает %s, режим ожидания: ядро подключается само", version, listen) } else { log.Printf("bj-lk %s (Личный кабинет) слушает %s, ядро: %s", version, listen, cfg.BJURL) } // Таймауты обязательны: кабинет стоит в интернете, и без них медленный клиент // может держать соединения сколько угодно. Ответ живёт дольше запроса — в режиме // ожидания страница ждёт, пока ядро заберёт запрос и ответит. hs := &http.Server{ Addr: listen, Handler: srv.Handler(), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 20 * time.Second, WriteTimeout: 60 * time.Second, IdleTimeout: 60 * time.Second, MaxHeaderBytes: 32 << 10, } if err := hs.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatal(err) } }