All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.king.platform.net.http.netty.sse.ServerEventDecoder Maven / Gradle / Ivy

// Copyright (C) king.com Ltd 2016
// https://github.com/king/king-http-client
// Author: Magnus Gustafsson
// License: Apache 2.0, https://raw.github.com/king/king-http-client/LICENSE-APACHE

package com.king.platform.net.http.netty.sse;


import com.king.platform.net.http.SseExecutionCallback;
import io.netty.buffer.ByteBuf;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.Executor;

public class ServerEventDecoder {
	private final SseExecutionCallback sseExecutionCallback;
	private final Executor httpClientCallbackExecutor;

	private StringBuilder buffer = new StringBuilder();
	private StringBuilder data = new StringBuilder();

	private String lastEventId;
	private String eventName;


	public ServerEventDecoder(SseExecutionCallback sseExecutionCallback, Executor httpClientCallbackExecutor) {
		this.sseExecutionCallback = sseExecutionCallback;
		this.httpClientCallbackExecutor = httpClientCallbackExecutor;

	}

	public void reset() {
		buffer.setLength(0);
		data.setLength(0);
		lastEventId = null;
		eventName = null;
	}

	public void onReceivedContentPart(ByteBuf content) {
		String contentString = content.toString(StandardCharsets.UTF_8);
		try {
			char[] chars = contentString.toCharArray();
			for (int i = 0; i < chars.length; i++) {
				char c = chars[i];

				if (isCRLF(i, chars)) {
					continue;
				}

				if (isNewLine(c)) {
					String line = buffer.toString();
					buffer.setLength(0);
					parseLine(line);
				} else {
					buffer.append(c);
				}

			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private boolean isCRLF(int index, char[] buffer) {
		if (buffer[index] != '\r') {
			return false;
		}

		if (index + 1 >= buffer.length) {
			return false;
		}

		return buffer[index+1] == '\n';
	}

	private void parseLine(String line) {
		line = line.trim();

		if (line.isEmpty()) {
			dispatchEvent();
			return;
		}

		if (line.startsWith(":")) {
			return;
		}

		int colonIndex;

		if ((colonIndex = line.indexOf(":")) != -1) {
			String field = line.substring(0, colonIndex);
			String value;
			if (line.charAt(colonIndex + 1) == ' ') {
				value = line.substring(colonIndex + 2);
			} else {
				value = line.substring(colonIndex + 1);
			}
			processField(field, value);
		} else {
			processField(line.trim(), "");
		}


	}

	private void processField(String field, String value) {
		switch (field.charAt(0)) {
			case 'd': {
				data.append(value).append("\n");
				break;
			}

			case 'i': {
				lastEventId = value;
				break;
			}

			case 'e': {
				eventName = value;
				break;
			}

			case 'r': {  //handle retry values from the server
				break;
			}
		}
	}

	private void dispatchEvent() {
		final String thisEventName = eventName;
		eventName = null;

		if (data.length() == 0) {
			return;
		}

		if (isNewLine(data.charAt(data.length()-1))) {
			data.setLength(data.length() - 1);
		}

		final String dataString = data.toString();
		data.setLength(0);

		httpClientCallbackExecutor.execute(new Runnable() {
			@Override
			public void run() {
				sseExecutionCallback.onEvent(lastEventId, thisEventName, dataString);
			}
		});

	}

	private boolean isNewLine(char c) {
		return c == '\r' || c == '\n';
	}


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy