Пример #1
0
void SSE::Client::HandleHandshake (const HTTP::Request& inRequest) {
    
    HTTP::Response response (HTTP::Code::BAD_REQUEST, inRequest.mVersion);
    
    bool isUpgraded (false);

    try {
        if (inRequest.GetHeaderValue ("Accept") == "text/event-stream" && 
            inRequest.mMethod == HTTP::Method::GET && 
            inRequest.mVersion == HTTP::Version::V11
        ) {
            
            // Standard SSE headers
            response.SetHeader (HTTP::Header ("Connection", "keep-alive"));
            response.SetHeader (HTTP::Header ("Content-Type", "text/event-stream"));
            
            // Prevent caching
            response.SetHeader (HTTP::Header ("Cache-Control", "no-cache"));
            
            // This SSE server most likely does not host the origin of the request
            // ==> Enable CORS.
            response.SetHeader (HTTP::Header ("Access-Control-Allow-Origin", "*"));
            response.SetHeader (HTTP::Header ("Access-Control-Allow-Credentials", "true"));
            
            // The response constructor sets the length to zero, this makes connections
            // assume there is no more data coming. Note: there is a stream in response, so the body 
            // has variable length! Remove this header.
            response.RemoveHeaders ("Content-Length"); 
            
            // Optionally check for last event ID.
            try {
                const auto list = inRequest.GetHeaders ("Last-Event-ID");
                if (!list.empty ()) {
                    uint8_t lastId = std::stoi (list[0].GetValue ());
                    mEventEncoder.SetLastId (lastId);
                }
            }
            catch (...) {}
            
            // Handshake completed.
            response.mCode = HTTP::Code::OK;
            isUpgraded = true;
        }
    } 
    catch (...) {}
    
    // Send the handshake response
    mResponseEncoder.Write (response);
    
    {
        using namespace HTTP;
        LOGINFO << "HTTP/" << VersionToString (response.mVersion) << " " << MethodToString (inRequest.mMethod) 
                << " " << inRequest.mPath << " - " << response.mCode << " " << CodeToString (response.mCode) << " - SSE";
    }
 
    if (!isUpgraded) {
        Quit ();
    }
    else {
        // Clear the read stream (SSE only contains outgoing events)
        GetReadStream ().Clear ();
        mResponseEncoder.Clear ();
        mToStringConverter.Clear ();
        mToPacketConverter.Clear ();
        mRequestDecoder.Clear ();
        mResponseEncoder.Clear ();
        mEventEncoder.Pipe (mToPacketConverter).Pipe (GetWriteStream ());
    }
}