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

org.zalando.fahrschein.http.simple.SimpleBufferingRequest Maven / Gradle / Ivy

package org.zalando.fahrschein.http.simple;

import org.zalando.fahrschein.http.api.Headers;
import org.zalando.fahrschein.http.api.HeadersImpl;
import org.zalando.fahrschein.http.api.Request;
import org.zalando.fahrschein.http.api.Response;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;

/**
 * {@link Request} implementation that uses standard JDK facilities to
 * execute buffered requests. Created via the {@link SimpleRequestFactory}.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @author Joern Horstmann
 * @see SimpleRequestFactory#createRequest(java.net.URI, String)
 */
final class SimpleBufferingRequest implements Request {

    private final HttpURLConnection connection;
    private final Headers headers;
    private ByteArrayOutputStream bufferedOutput;
    private boolean executed;

    SimpleBufferingRequest(HttpURLConnection connection) {
        this.connection = connection;
        this.headers = new HeadersImpl();
    }

    @Override
    public String getMethod() {
        return this.connection.getRequestMethod();
    }

    @Override
    public URI getURI() {
        try {
            return this.connection.getURL().toURI();
        } catch (URISyntaxException ex) {
            throw new IllegalStateException("Could not get HttpURLConnection URI: " + ex.getMessage(), ex);
        }
    }

    private Response executeInternal() throws IOException {
        final int size = this.bufferedOutput != null ? this.bufferedOutput.size() : 0;
        if (this.headers.getContentLength() < 0) {
            this.headers.setContentLength(size);
        }

        for (String headerName : headers.headerNames()) {
            final List value = headers.get(headerName);
            for (String headerValue : value) {
                final String actualHeaderValue = headerValue != null ? headerValue : "";
                connection.addRequestProperty(headerName, actualHeaderValue);
            }
        }

        // JDK <1.8 doesn't support getOutputStream with HTTP DELETE
        if ("DELETE".equals(getMethod()) && size > 0) {
            this.connection.setDoOutput(false);
        }
        if (this.connection.getDoOutput()) {
            this.connection.setFixedLengthStreamingMode(size);
        }

        this.connection.connect();

        if (this.connection.getDoOutput() && this.bufferedOutput != null) {
            this.bufferedOutput.writeTo(this.connection.getOutputStream());
        } else {
            // Immediately trigger the request in a no-output scenario as well
            this.connection.getResponseCode();
        }

        final Response result = new SimpleResponse(this.connection);
        this.bufferedOutput = null;
        return result;
    }

    @Override
    public final Headers getHeaders() {
        return (this.executed ? new HeadersImpl(this.headers, true) : this.headers);
    }

    @Override
    public final OutputStream getBody() throws IOException {
        assertNotExecuted();
        if (this.bufferedOutput == null) {
            this.bufferedOutput = new ByteArrayOutputStream(1024);
        }
        return this.bufferedOutput;
    }

    @Override
    public final Response execute() throws IOException {
        assertNotExecuted();
        final Response result = executeInternal();
        this.executed = true;
        return result;
    }

    /**
     * Assert that this request has not been {@linkplain #execute() executed} yet.
     * @throws IllegalStateException if this request has been executed
     */
    protected void assertNotExecuted() {
        if (this.executed) {
            throw new IllegalStateException("ClientHttpRequest already executed");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy