void WebClientApp::onReadComplete()
{
	mText.push_back( "Read complete" );
	
	console() << "HTTP version: ";
	switch ( mHttpResponse.getHttpVersion() ) {
		case HttpVersion::HTTP_0_9:
			console() << "0.9";
			break;
		case HttpVersion::HTTP_1_0:
			console() << "1.0";
			break;
		case HttpVersion::HTTP_1_1:
			console() << "1.1";
			break;
		case HttpVersion::HTTP_2_0:
			console() << "2.0";
			break;
	}
	console() << endl;
	console() << "Status code: " << mHttpResponse.getStatusCode() << endl;
	console() << "Reason: " << mHttpResponse.getReason() << endl;
	
	console() << "Header fields: " << endl;
	for ( const KeyValuePair& kvp : mHttpResponse.getHeaders() ) {
		console() << ">> " << kvp.first << ": " << kvp.second << endl;
	}
	console() << endl;
	
	console() << "Body:" << endl;
	console() << HttpResponse::bufferToString( mHttpResponse.getBody() ) << endl;

	mSession->close();
}
void TcpClientApp::onRead( ci::Buffer buffer )
{
	mText.push_back( toString( buffer.getDataSize() ) + " bytes read" );
	
	// Responses are passed in the read callback as ci::Buffer. Use
	// a convenience method on the session object to convert it to
	// a std::string.
	string response	= TcpSession::bufferToString( buffer );
	mText.push_back( response );
	
	// Closing the connection after reading mimics the behavior
	// of a HTTP client. To keep the connection open and continue
	// communicating with the server, comment the line below.
	mSession->close();
}
void HttpClientApp::onRead( ci::BufferRef buffer )
{
	size_t sz	= buffer->getSize();
	mBytesRead	+= sz;
	mText.push_back( toString( sz ) + " bytes read" );
	
	if ( !mHttpResponse.hasHeader() ) {
		
		// Parse header
		mHttpResponse.parseHeader( HttpResponse::bufferToString( buffer ) );
		buffer = HttpResponse::removeHeader( buffer );
		
		// Get content-length
		for ( const KeyValuePair& kvp : mHttpResponse.getHeaders() ) {
			if ( kvp.first == "Content-Length" ) {
				mContentLength = fromString<size_t>( kvp.second );
				break;
			}
		}
	}
	
	// Append buffer to body
	mHttpResponse.append( buffer );
	
	if ( mBytesRead < mContentLength ) {
		
		// Keep reading until we hit the content length
		mSession->read();
	} else {

		mText.push_back( "Read complete" );
		mText.push_back( toString( mHttpResponse.getStatusCode() ) + " " + mHttpResponse.getReason() );
		
		if ( mHttpResponse.getStatusCode() == 200 ) {
			for ( const KeyValuePair& kvp : mHttpResponse.getHeaders() ) {
				
				// Choose file extension based on MIME type
				if ( kvp.first == "Content-Type" ) {
					string mime = kvp.second;
					
					if ( mime == "audio/mp3" ) {
						mFilename += ".mp3";
					} else if ( mime == "image/jpeg" ) {
						mFilename += ".jpg";
					} else if ( mime == "image/png" ) {
						mFilename += ".png";
					}
				} else if ( kvp.first == "Connection" ) {
					
					// Close connection if requested by server
					if ( kvp.second == "close" ) {
						mSession->close();
					}
				}
			}

			// Save the file
			fs::path path = getAppPath();
#if !defined ( CINDER_MSW )
			path = path.parent_path();
#endif
			path = path / mFilename;
			OStreamFileRef file = writeFileStream( path );
			file->write( mHttpResponse.getBody() );
			
			mText.push_back( mFilename + " downloaded" );
		} else {
			
			// Write error
			mText.push_back( "Response: " +  HttpResponse::bufferToString( mHttpResponse.getBody() ) );
			
			mSession->close();
		}
	}
}