package io.github.azagniotov.stubby4j.http; import io.github.azagniotov.stubby4j.cli.ANSITerminal; import io.github.azagniotov.stubby4j.client.StubbyResponse; import io.github.azagniotov.stubby4j.stubs.StubRequest; import io.github.azagniotov.stubby4j.utils.ConsoleUtils; import io.github.azagniotov.stubby4j.utils.StringUtils; import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.HashSet; import java.util.Map; import java.util.Set; import static io.github.azagniotov.stubby4j.common.Common.POSTING_METHODS; import static io.github.azagniotov.stubby4j.utils.StringUtils.charsetUTF8; import static io.github.azagniotov.stubby4j.utils.StringUtils.inputStreamToString; import static java.lang.String.valueOf; import static java.util.Map.Entry; import static org.eclipse.jetty.http.HttpHeader.CONTENT_ENCODING; import static org.eclipse.jetty.http.HttpHeader.CONTENT_LANGUAGE; import static org.eclipse.jetty.http.HttpHeader.CONTENT_LENGTH; import static org.eclipse.jetty.http.HttpHeader.CONTENT_TYPE; /** * @author Alexander Zagniotov * @since 11/4/12, 11:03 AM */ public class StubbyHttpTransport { private static final Set<String> SUPPORTED_METHODS = new HashSet<String>() {{ add(HttpMethod.GET.asString()); add(HttpMethod.HEAD.asString()); add(HttpMethod.TRACE.asString()); add(HttpMethod.OPTIONS.asString()); add(HttpMethod.DELETE.asString()); add(HttpMethod.POST.asString()); add(HttpMethod.PUT.asString()); }}; public StubbyHttpTransport() { } public StubbyResponse fetchRecordableHTTPResponse(final StubRequest request, final String recordingSource) throws IOException { final String method = request.getMethod().get(0); if (!ANSITerminal.isMute()) { final String logMessage = String.format("[%s] -> Recording HTTP response using %s [%s]", ConsoleUtils.getTime(), method, recordingSource); ANSITerminal.incoming(logMessage); } return getResponse(method, recordingSource, request.getPostBody(), request.getHeaders(), StringUtils.calculateStringLength(request.getPostBody())); } public StubbyResponse getResponse(final String method, final String fullUrl, final String post, final Map<String, String> headers, final int postLength) throws IOException { if (!SUPPORTED_METHODS.contains(method)) { throw new UnsupportedOperationException(String.format("HTTP method '%s' not supported when contacting stubby4j", method)); } final URL url = new URL(fullUrl); final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod(method); connection.setUseCaches(false); connection.setInstanceFollowRedirects(false); setRequestHeaders(connection, headers, postLength); if (POSTING_METHODS.contains(method)) { writePost(connection, post); } return buildStubbyResponse(connection); } private StubbyResponse buildStubbyResponse(final HttpURLConnection connection) throws IOException { try { connection.connect(); final int responseCode = connection.getResponseCode(); if (responseCode == HttpStatus.OK_200 || responseCode == HttpStatus.CREATED_201) { try (final InputStream inputStream = connection.getInputStream()) { final String responseContent = inputStreamToString(inputStream); return new StubbyResponse(responseCode, responseContent); } } return new StubbyResponse(responseCode, connection.getResponseMessage()); } finally { connection.disconnect(); } } private void setRequestHeaders(final HttpURLConnection connection, final Map<String, String> headers, final int postLength) { connection.setRequestProperty("User-Agent", StringUtils.constructUserAgentName()); final String requestMethod = connection.getRequestMethod(); if (POSTING_METHODS.contains(StringUtils.toUpper(requestMethod))) { connection.setDoOutput(true); connection.setRequestProperty(CONTENT_TYPE.asString(), "application/x-www-form-urlencoded"); connection.setRequestProperty(CONTENT_LANGUAGE.asString(), "en-US"); connection.setRequestProperty(CONTENT_ENCODING.asString(), StringUtils.UTF_8); connection.setRequestProperty(CONTENT_LENGTH.asString(), valueOf(postLength)); if (postLength > 0) { connection.setFixedLengthStreamingMode(postLength); } else { connection.setChunkedStreamingMode(0); } } for (final Entry<String, String> entry : headers.entrySet()) { connection.setRequestProperty(entry.getKey(), entry.getValue()); } } private void writePost(final HttpURLConnection connection, final String post) throws IOException { try (final OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream(), charsetUTF8()); final BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter)) { bufferedWriter.write(post); } } }