MCPcopy
hub / github.com/tinode/chat / serveLongPoll

Function serveLongPoll

server/hdl_longpoll.go:124–205  ·  view source on GitHub ↗

serveLongPoll handles long poll connections when WebSocket is not available Connection could be without sid or with sid: - if sid is empty, create session, expect a login in the same request, respond and close - if sid is not empty and there is an initialized session, payload is optional - if no pay

(wrt http.ResponseWriter, req *http.Request)

Source from the content-addressed store, hash-verified

122// - if payload exists, process it and close
123// - if sid is not empty but there is no session, report an error
124func serveLongPoll(wrt http.ResponseWriter, req *http.Request) {
125 now := time.Now().UTC().Round(time.Millisecond)
126
127 // Use the lowest common denominator - this is a legacy handler after all (otherwise would use application/json)
128 wrt.Header().Set("Content-Type", "text/plain")
129 if globals.tlsStrictMaxAge != "" {
130 wrt.Header().Set("Strict-Transport-Security", "max-age"+globals.tlsStrictMaxAge)
131 }
132
133 enc := json.NewEncoder(wrt)
134
135 if isValid, _ := checkAPIKey(getAPIKey(req)); !isValid {
136 wrt.WriteHeader(http.StatusForbidden)
137 enc.Encode(ErrAPIKeyRequired(now))
138 return
139 }
140
141 // TODO(gene): should it be configurable?
142 // Currently any domain is allowed to get data from the chat server
143 wrt.Header().Set("Access-Control-Allow-Origin", "*")
144
145 // Ensure the response is not cached
146 if req.ProtoAtLeast(1, 1) {
147 wrt.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1
148 } else {
149 wrt.Header().Set("Pragma", "no-cache") // HTTP 1.0
150 }
151 wrt.Header().Set("Expires", "0") // Proxies
152
153 // TODO(gene): respond differently to valious HTTP methods
154
155 // Get session id
156 sid := req.FormValue("sid")
157 var sess *Session
158 if sid == "" {
159 // New session
160 var count int
161 sess, count = globals.sessionStore.NewSession(wrt, "")
162 sess.remoteAddr = getRemoteAddr(req)
163 logs.Info.Println("longPoll: session started", sess.sid, sess.remoteAddr, count)
164
165 wrt.WriteHeader(http.StatusCreated)
166 pkt := NoErrCreated(req.FormValue("id"), "", now)
167 pkt.Ctrl.Params = map[string]string{
168 "sid": sess.sid,
169 }
170 enc.Encode(pkt)
171
172 return
173 }
174
175 // Existing session
176 sess = globals.sessionStore.Get(sid)
177 if sess == nil {
178 logs.Warn.Println("longPoll: invalid or expired session id", sid)
179 wrt.WriteHeader(http.StatusForbidden)
180 enc.Encode(ErrSessionNotFound(now))
181 return

Callers

nothing calls this directly

Calls 13

readOnceMethod · 0.95
writeOnceMethod · 0.95
checkAPIKeyFunction · 0.85
getAPIKeyFunction · 0.85
ErrAPIKeyRequiredFunction · 0.85
getRemoteAddrFunction · 0.85
NoErrCreatedFunction · 0.85
ErrSessionNotFoundFunction · 0.85
ErrMalformedFunction · 0.85
WriteHeaderMethod · 0.80
NewSessionMethod · 0.80
PrintlnMethod · 0.80

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…