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

org.webpieces.frontend.impl.Http11ResponseSender Maven / Gradle / Ivy

Go to download

Create a webserver with this library in just 3 lines of code. just register your HttpRequestListener and it feeds you a FrontendSocket that you write HttpResponses to

There is a newer version: 1.9.71
Show newest version
package org.webpieces.frontend.impl;

import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import org.webpieces.data.api.DataWrapper;
import org.webpieces.httpcommon.Responses;
import org.webpieces.httpcommon.api.Protocol;
import org.webpieces.httpcommon.api.RequestId;
import org.webpieces.httpcommon.api.ResponseId;
import org.webpieces.httpcommon.api.ResponseSender;
import org.webpieces.httpcommon.api.exceptions.HttpException;
import org.webpieces.httpparser.api.HttpParser;
import org.webpieces.httpparser.api.common.Header;
import org.webpieces.httpparser.api.common.KnownHeaderName;
import org.webpieces.httpparser.api.dto.HttpChunk;
import org.webpieces.httpparser.api.dto.HttpLastChunk;
import org.webpieces.httpparser.api.dto.HttpRequest;
import org.webpieces.httpparser.api.dto.HttpResponse;
import org.webpieces.httpparser.api.dto.HttpResponseStatus;
import org.webpieces.httpparser.api.dto.HttpResponseStatusLine;
import org.webpieces.nio.api.channels.Channel;

import com.webpieces.http2parser.api.dto.lib.Http2Header;

class Http11ResponseSender implements ResponseSender {

	private Channel channel;
	private HttpParser parser;

	public Http11ResponseSender(Channel channel, HttpParser parser) {
		this.channel = channel;
		this.parser = parser;
	}

	@Override
	public Protocol getProtocol() {
		return Protocol.HTTP11;
	}

	@Override
	public CompletableFuture close() {
		return channel.close().thenAccept(c -> {});
	}

	private CompletableFuture actuallySendResponse(HttpResponse response) {
		ByteBuffer data = parser.marshalToByteBuffer(response);
		return channel.write(data).thenAccept(c -> {});

	}
	@Override
	public CompletableFuture sendResponse(HttpResponse response, HttpRequest request, RequestId requestId, boolean isComplete) {
		// HTTP/1.1 doesn't need responseids
		ResponseId id = new ResponseId(0);

		if(isComplete) {
			return actuallySendResponse(response)
					.thenApply(v -> id);
		} else {
			HttpResponse responseNoBody = Responses.copyResponseExceptBody(response);
			DataWrapper body = response.getBodyNonNull();
			// If we're not already chunked, make it chunked.
			Header transferEncodingHeader = responseNoBody.getHeaderLookupStruct().getHeader(KnownHeaderName.TRANSFER_ENCODING);
			if(transferEncodingHeader == null || !transferEncodingHeader.getValue().equalsIgnoreCase("chunked")) {
				responseNoBody.addHeader(new Header(KnownHeaderName.TRANSFER_ENCODING, "chunked"));
			}
			return actuallySendResponse(responseNoBody)
					.thenAccept(v -> {
						if(body.getReadableSize() != 0)
							sendData(body, id, false);
					})
					.thenApply(v -> id);
		}
	}

	@Override
	public CompletableFuture sendData(DataWrapper data, ResponseId id, boolean isComplete) {
		// Create a chunk from the data, then send.
		HttpChunk chunk;
		if(isComplete) {
			chunk = new HttpLastChunk();
		} else
		{
			chunk = new HttpChunk();
		}
		chunk.setBody(data);
		return channel.write(parser.marshalToByteBuffer(chunk)).thenAccept(c -> {});
	}

	@Override
	public void sendTrailer(List headerList, ResponseId id, boolean isComplete) {
		if(!isComplete) {
			throw new RuntimeException("can't sendTrailer that isnot completeing the response");
		}
		HttpLastChunk lastChunk = new HttpLastChunk();
		for(Http2Header header: headerList) {
			lastChunk.addHeader(new Header(header.getName(), header.getValue()));
		}
		channel.write(parser.marshalToByteBuffer(lastChunk));
	}

	@Override
	public CompletableFuture sendException(HttpException e) {

		HttpResponseStatus respStatus = new HttpResponseStatus();
		respStatus.setKnownStatus(e.getStatusCode());
		HttpResponseStatusLine statusLine = new HttpResponseStatusLine();
		statusLine.setStatus(respStatus);

		HttpResponse response = new HttpResponse();
		response.setStatusLine(statusLine );

		response.addHeader(new Header("Failure", e.getMessage()));
		ByteBuffer data = parser.marshalToByteBuffer(response);

		return channel.write(data).thenAccept(c -> {});
	}

	@Override
	public Channel getUnderlyingChannel() {
		return channel;
	}

	@Override
	public String toString() {
		return "ResponseSender[" + channel + "]";
	}

	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy