package lkgateway // lkcabinet.go — кабинет клиента, собранный внутрь ядра. // // Страницы кабинета рисует ядро: у него все данные и шаблоны (пакет modules/lk — тот же, // что собирается в самостоятельный bj-lk). На хостинге остаётся ретранслятор, который // передаёт запросы браузера конвертами: в прямом режиме — POST /api/lk/render, в режиме // ожидания — ядро само забирает конверты из очереди ретранслятора (lkagent.go). // // Данные встроенный кабинет берёт через тот же API /api/lk/*, вызывая обработчик внутри // процесса: граница проверок одна и та же, где бы кабинет ни работал. import ( "encoding/json" "io" "log" "net/http" "strings" "sync" "git.zetit.ru/zuevav/Bridge-and-Join-s/modules/lk" ) // globalLKCabinet — встроенный кабинет; им пользуется и цикл режима ожидания. var globalLKCabinet *lkCabinet // lkCabinet — встроенный кабинет; пересобирается, если сменился заголовок. type lkCabinet struct { mu sync.Mutex api http.Handler rc *RuntimeConfig srv *lk.Server title string } func newLKCabinet(api http.Handler, rc *RuntimeConfig) *lkCabinet { return &lkCabinet{api: api, rc: rc} } // server — кабинет с актуальным заголовком организации. func (c *lkCabinet) server() (*lk.Server, error) { s := c.rc.Snapshot() title := strings.TrimSpace(orgName(s)) if title == "" { title = "Личный кабинет" } else { title += " · личный кабинет" } c.mu.Lock() defer c.mu.Unlock() if c.srv != nil && c.title == title { return c.srv, nil } srv, err := lk.New(lk.Config{Title: title, Local: c.api, LocalKey: func() string { return c.rc.Snapshot().LK.APIKey }}) if err != nil { return nil, err } c.srv, c.title = srv, title return srv, nil } // serve — выполнить конверт страницы. func (c *lkCabinet) serve(r *http.Request, env lk.PageRequest) lk.PageResponse { srv, err := c.server() if err != nil { log.Printf("кабинет: не собран: %v", err) return lk.PageResponse{ID: env.ID, Status: http.StatusInternalServerError, Body: []byte("кабинет не собран")} } return srv.ServeEnvelope(r.Context(), env) } // registerRender — POST /api/lk/render: ретранслятор в прямом режиме присылает конверт // запроса браузера, получает конверт ответа. Только по ключу модуля. func (c *lkCabinet) registerRender(mux *http.ServeMux, auth func(http.ResponseWriter, *http.Request) bool) { mux.HandleFunc("/api/lk/render", func(w http.ResponseWriter, r *http.Request) { if !auth(w, r) { return } if r.Method != http.MethodPost { lkJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "нужен POST"}) return } var env lk.PageRequest if err := json.NewDecoder(io.LimitReader(r.Body, 2<<20)).Decode(&env); err != nil { lkJSON(w, http.StatusBadRequest, map[string]string{"error": "конверт не разобран"}) return } if env.Kind != "page" { lkJSON(w, http.StatusBadRequest, map[string]string{"error": "через render идут только страницы"}) return } lkJSON(w, http.StatusOK, c.serve(r, env)) }) }