
io.reactivex.netty.protocol.http.sse.ServerSentEvent Maven / Gradle / Ivy
/*
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.reactivex.netty.protocol.http.sse;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
/**
* An object representing a server-sent-event following the SSE specifications
*
* A server sent event is composed of the following:
*
*
- Event id: This is the last event id seen on the stream this event was received. This can be null, if no id is received.
- Event type: The last seen event type seen on the stream this event was received. This can be null, if no type is received.
- Data: This is the actual event data.
*
* Type
*
* A {@link ServerSentEvent} is of the type {@link Type#Data} unless it is explicitly passed on creation.
*
* Memory management
*
* This is an implementation of {@link ByteBufHolder} so it is required to be explicitly released by calling
* {@link #release()} when this instance is no longer required.
*
* @author Nitesh Kant
*/
public class ServerSentEvent implements ByteBufHolder {
private static final Logger logger = LoggerFactory.getLogger(ServerSentEvent.class);
private static Charset sseEncodingCharset;
static {
try {
sseEncodingCharset = Charset.forName("UTF-8");
} catch (Exception e) {
logger.error("UTF-8 charset not available. Since SSE only contains UTF-8 data, we can not read SSE data.");
sseEncodingCharset = null;
}
}
public enum Type {
Data,
Id,
EventType
}
private final Type type;
private final ByteBuf data;
private final ByteBuf eventId;
private final ByteBuf eventType;
public ServerSentEvent(Type type, ByteBuf data) {
this(type, null, null, data);
}
public ServerSentEvent(ByteBuf data) {
this(Type.Data, data);
}
public ServerSentEvent(ByteBuf eventId, ByteBuf eventType, ByteBuf data) {
this(Type.Data, eventId, eventType, data);
}
protected ServerSentEvent(Type type, ByteBuf eventId, ByteBuf eventType, ByteBuf data) {
this.data = data;
this.type = type;
this.eventId = eventId;
this.eventType = eventType;
}
/**
* The type of this event. For events which contain an event Id or event type along with data, the type is still
* {@link Type#Data}. The type will be {@link Type#Id} or {@link Type#EventType} only if the event just contains the
* event type or event id and no data.
*
* @return Type of this event.
*/
public Type getType() {
return type;
}
public boolean hasEventId() {
return null != eventId;
}
public boolean hasEventType() {
return null != eventType;
}
public ByteBuf getEventId() {
return eventId;
}
public String getEventIdAsString() {
return eventId.toString(getSseCharset());
}
public ByteBuf getEventType() {
return eventType;
}
public String getEventTypeAsString() {
return eventType.toString(getSseCharset());
}
public String contentAsString() {
return data.toString(getSseCharset());
}
@Override
public ByteBuf content() {
return data;
}
@Override
public ByteBufHolder copy() {
return new ServerSentEvent(type, null != eventId ? eventId.copy() : null,
null != eventType ? eventType.copy() : null, data.copy());
}
@Override
public ByteBufHolder duplicate() {
return new ServerSentEvent(type, null != eventId ? eventId.duplicate() : null,
null != eventType ? eventType.duplicate() : null, data.duplicate());
}
@Override
public int refCnt() {
return data.refCnt(); // Ref count is consistent across data, eventId and eventType
}
@Override
public ByteBufHolder touch() {
if(hasEventId()) {
eventId.touch();
}
if(hasEventType()) {
eventType.touch();
}
data.touch();
return this;
}
@Override
public ByteBufHolder touch(Object hint) {
if(hasEventId()) {
eventId.touch(hint);
}
if(hasEventType()) {
eventType.touch(hint);
}
data.touch(hint);
return this;
}
@Override
public ByteBufHolder retain() {
if(hasEventId()) {
eventId.retain();
}
if(hasEventType()) {
eventType.retain();
}
data.retain();
return this;
}
@Override
public ByteBufHolder retain(int increment) {
if(hasEventId()) {
eventId.retain(increment);
}
if(hasEventType()) {
eventType.retain(increment);
}
data.retain(increment);
return this;
}
@Override
public boolean release() {
if(hasEventId()) {
eventId.release();
}
if(hasEventType()) {
eventType.release();
}
return data.release();
}
@Override
public boolean release(int decrement) {
if(hasEventId()) {
eventId.release(decrement);
}
if(hasEventType()) {
eventType.release(decrement);
}
return data.release(decrement);
}
/**
* Creates a {@link ServerSentEvent} instance with an event id.
*
* @param eventId Id for the event.
* @param data Data for the event.
*
* @return The {@link ServerSentEvent} instance.
*/
public static ServerSentEvent withEventId(ByteBuf eventId, ByteBuf data) {
return new ServerSentEvent(eventId, null, data);
}
/**
* Creates a {@link ServerSentEvent} instance with an event type.
*
* @param eventType Type for the event.
* @param data Data for the event.
*
* @return The {@link ServerSentEvent} instance.
*/
public static ServerSentEvent withEventType(ByteBuf eventType, ByteBuf data) {
return new ServerSentEvent(null, eventType, data);
}
/**
* Creates a {@link ServerSentEvent} instance with an event id and type.
*
* @param eventType Type for the event.
* @param eventId Id for the event.
* @param data Data for the event.
*
* @return The {@link ServerSentEvent} instance.
*/
public static ServerSentEvent withEventIdAndType(ByteBuf eventId, ByteBuf eventType, ByteBuf data) {
return new ServerSentEvent(eventId, eventType, data);
}
protected Charset getSseCharset() {
return null == sseEncodingCharset ? Charset.forName("UTF-8") : sseEncodingCharset;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy