bool HTTPSession::ParseRequest(HTTPRequest& request, ReadBuffer& cmd, UrlParam& params) { char* qmark; ReadBuffer rb; ReadBuffer jsonCallback; ReadBuffer mimeType; ReadBuffer origin; // TODO: when adding keep-alive HTTP sessions, move this to an Init() function isFlushed = false; uri = request.line.uri; rb = request.line.uri; if (rb.GetCharAt(0) == '/') rb.Advance(1); mimeType.Reset(); ParseType(rb); cmd = rb; qmark = NULL; if (rb.GetLength() > 0) qmark = FindInBuffer(rb.GetBuffer(), rb.GetLength() - 1, '?'); if (qmark) { rb.Advance((unsigned) (qmark - rb.GetBuffer() + 1)); params.Init(rb.GetBuffer(), rb.GetLength(), '&'); cmd.SetLength((unsigned) (qmark - cmd.GetBuffer())); if (type == JSON) { HTTP_GET_OPT_PARAM(params, "callback", jsonCallback); json.SetCallbackPrefix(jsonCallback); } // mime type is overridable HTTP_GET_OPT_PARAM(params, "mimetype", mimeType); if (mimeType.GetLength() != 0) conn->SetContentType(mimeType); // CORS support // http://www.w3.org/TR/cors/ HTTP_GET_OPT_PARAM(params, "origin", origin); } return true; }
bool UrlParam::GetNamed(const char* name, int namelen, ReadBuffer& bs) { int n; int len; n = GetParamIndex(name, namelen); if (n < 0) return false; len = GetParamLen(n) - (namelen + 1); if (len == -1) len = 0; // param without value bs.SetBuffer((char*) GetParam(n) + (namelen + 1)); bs.SetLength(len); return true; }
void MessageConnection::OnRead() { bool yield, closed; unsigned pos, msglength, nread, msgbegin, msgend, required; uint64_t start; Stopwatch sw; ReadBuffer msg; if (!readActive) { if (resumeRead.IsActive()) STOP_FAIL(1, "Program bug: resumeRead.IsActive() should be false."); EventLoop::Add(&resumeRead); return; } sw.Start(); Log_Trace("Read buffer: %B", tcpread.buffer); tcpread.requested = IO_READ_ANY; pos = 0; start = NowClock(); yield = false; while(true) { msglength = BufferToUInt64(tcpread.buffer->GetBuffer() + pos, tcpread.buffer->GetLength() - pos, &nread); if (msglength > tcpread.buffer->GetSize() - NumDigits(msglength) - 1) { Log_Trace(); required = msglength + NumDigits(msglength) + 1; if (required > MESSAGING_MAX_SIZE) { Log_Trace(); OnClose(); return; } tcpread.buffer->Allocate(required); break; } if (nread == 0 || (unsigned) tcpread.buffer->GetLength() - pos <= nread) break; if (tcpread.buffer->GetCharAt(pos + nread) != ':') { Log_Trace("Message protocol error"); OnClose(); return; } msgbegin = pos + nread + 1; msgend = pos + nread + 1 + msglength; if ((unsigned) tcpread.buffer->GetLength() < msgend) { // read more //tcpread.requested = msgend - pos; break; } msg.SetBuffer(tcpread.buffer->GetBuffer() + msgbegin); msg.SetLength(msglength); closed = OnMessage(msg); if (closed) return; pos = msgend; // if the user called Close() in OnMessageRead() if (state != CONNECTED) return; if (tcpread.buffer->GetLength() == msgend) break; if (NowClock() - start >= YIELD_TIME || !readActive) { // let other code run every YIELD_TIME msec yield = true; if (resumeRead.IsActive()) STOP_FAIL(1, "Program bug: resumeRead.IsActive() should be false."); EventLoop::Add(&resumeRead); break; } } if (pos > 0) { memmove(tcpread.buffer->GetBuffer(), tcpread.buffer->GetBuffer() + pos, tcpread.buffer->GetLength() - pos); tcpread.buffer->Shorten(pos); } if (state == CONNECTED && !tcpread.active && !yield) IOProcessor::Add(&tcpread); sw.Stop(); Log_Trace("time spent in OnRead(): %U", sw.Elapsed()); }