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

org.jboss.resteasy.plugins.server.vertx.VertxHttpResponse Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha4
Show newest version
package org.jboss.resteasy.plugins.server.vertx;

import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.NewCookie;
import jakarta.ws.rs.ext.RuntimeDelegate;

import org.jboss.resteasy.plugins.server.vertx.i18n.Messages;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory;

import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServerResponse;

public class VertxHttpResponse implements HttpResponse {
    private int status = 200;
    private OutputStream os;
    private MultivaluedMap outputHeaders;
    final HttpServerResponse response;
    private boolean committed;
    private ResteasyProviderFactory providerFactory;
    private final HttpMethod method;
    private Throwable vertxException;
    private boolean ended;

    public VertxHttpResponse(final HttpServerResponse response, final ResteasyProviderFactory providerFactory) {
        this(response, providerFactory, null);
    }

    public VertxHttpResponse(final HttpServerResponse response, final ResteasyProviderFactory providerFactory,
            final HttpMethod method) {
        outputHeaders = new MultivaluedMapImpl();
        this.method = method;
        os = (method == null || !method.equals(HttpMethod.HEAD)) ? new ChunkOutputStream(this, 1000) : null;
        this.response = response;
        this.providerFactory = providerFactory;
        response.exceptionHandler(t -> vertxException = t);
        response.closeHandler(v -> vertxException = new IOException("Connection closed"));
    }

    @Override
    public void setOutputStream(OutputStream os) {
        this.os = os;
    }

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public MultivaluedMap getOutputHeaders() {
        return outputHeaders;
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        return os;
    }

    @Override
    public void addNewCookie(NewCookie cookie) {
        outputHeaders.add(jakarta.ws.rs.core.HttpHeaders.SET_COOKIE, cookie);
    }

    void checkException() throws IOException {
        if (vertxException instanceof IOException)
            throw (IOException) vertxException;
        if (vertxException != null)
            throw new IOException(vertxException);
    }

    @Override
    public void sendError(int status) throws IOException {
        checkException();
        sendError(status, null);
    }

    @Override
    public void sendError(int status, String message) throws IOException {
        checkException();
        if (committed) {
            throw new IllegalStateException();
        }
        response.setStatusCode(status);
        if (message != null) {
            response.end(message);
        } else {
            response.end();
        }
        committed = true;
        ended = true;
    }

    @Override
    public boolean isCommitted() {
        return committed;
    }

    @Override
    public void reset() {
        if (committed) {
            throw new IllegalStateException(Messages.MESSAGES.alreadyCommitted());
        }
        outputHeaders.clear();
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void transformHeaders(VertxHttpResponse vertxResponse, HttpServerResponse response,
            ResteasyProviderFactory factory) {
        for (Map.Entry> entry : vertxResponse.getOutputHeaders().entrySet()) {
            String key = entry.getKey();
            for (Object value : entry.getValue()) {
                RuntimeDelegate.HeaderDelegate delegate = factory.getHeaderDelegate(value.getClass());
                if (delegate != null) {
                    response.headers().add(key, delegate.toString(value));
                } else {
                    response.headers().add(key, value.toString());
                }
            }
        }
    }

    public void prepareChunkStream() {
        committed = true;
        response.setStatusCode(getStatus());
        response.setChunked(true);
        transformHeaders(this, response, providerFactory);
    }

    private void prepareEmptyResponse() {
        committed = true;
        response.setStatusCode(getStatus());
        transformHeaders(this, response, providerFactory);
        response.headersEndHandler(h -> {
            response.headers().remove(HttpHeaders.CONTENT_LENGTH);
            response.headers().set(HttpHeaders.CONNECTION, HttpHeaders.KEEP_ALIVE);
        });
    }

    public void finish() throws IOException {
        if (ended)
            return;
        ended = true;
        checkException();
        if (os != null) {
            os.flush();
            if (!isCommitted()) {
                prepareChunkStream();
            }
        } else {
            prepareEmptyResponse();
        }
        response.end();
    }

    @Override
    public void flushBuffer() throws IOException {
        checkException();
        if (os != null) {
            os.flush();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy